﻿using System;
using System.IO;
using System.Management;
using System.Diagnostics;

namespace HyperV
{
    public partial class VMHelper
    {

        private static string GetVirtualSystemExportSettingDataInstance(ManagementScope scope, ManagementObject snapshotSettingData)
        {
            ManagementPath settingPath = new ManagementPath("Msvm_VirtualSystemExportSettingData");

            ManagementClass exportSettingDataClass = new ManagementClass(scope, settingPath, null);
            ManagementObject exportSettingData = exportSettingDataClass.CreateInstance();

            exportSettingData["CopySnapshotConfiguration"] = 2;
            exportSettingData["CreateVmExportSubdirectory"] = true;
            exportSettingData["SnapshotVirtualSystem"] = snapshotSettingData.Path.Path;

            string settingData = exportSettingData.GetText(TextFormat.CimDtd20);

            exportSettingData.Dispose();
            exportSettingDataClass.Dispose();

            return settingData;
        }


        private static void ExportVirtualSystemExSnapshots(ManagementScope scope, string vmName, string exportDirectory)
        {
            
            ManagementObject virtualSystemService = Utility.GetServiceObject(scope, "Msvm_VirtualSystemManagementService");

            ManagementBaseObject inParams = virtualSystemService.GetMethodParameters("ExportVirtualSystemEx");

            ManagementObject vm = Utility.GetTargetComputer(vmName, scope);
            ManagementObject snapshotSettingData = GetLastVirtualSystemSnapshot(vm);

            if (snapshotSettingData == null)
            {
                Debug.WriteLine("There are not snapshots in the VM to be exported...");
                return;
            }

            inParams["ComputerSystem"] = vm.Path.Path;

            inParams["ExportDirectory"] = exportDirectory;
            inParams["ExportSettingData"] = GetVirtualSystemExportSettingDataInstance(scope, snapshotSettingData);

            ManagementBaseObject outParams = virtualSystemService.InvokeMethod("ExportVirtualSystemEx", inParams, null);

            if ((UInt32)outParams["ReturnValue"] == ReturnCode.Started)
            {
                if (Utility.JobCompleted(outParams, scope))
                {
                    Debug.WriteLine("VM '{0}' were exported successfully.", vm["ElementName"]);
                }
                else
                {
                    Debug.WriteLine("Failed to export VM");
                }
            }
            else if ((UInt32)outParams["ReturnValue"] == ReturnCode.Completed)
            {
                Debug.WriteLine("VM '{0}' were exported successfully.", vm["ElementName"]);
            }
            else
            {
                Debug.WriteLine("Export virtual system failed with error:{0}", outParams["ReturnValue"]);
            }

            inParams.Dispose();
            outParams.Dispose();
            vm.Dispose();
            virtualSystemService.Dispose();
        }

        public void TakeSnapshot(String vmName, String exportDirectory)
        {
            ExportVirtualSystemExSnapshots(Scope, vmName, exportDirectory);
        }

        public static void TakeSnapshot(ManagementScope scope, String vmName, String exportDirectory)
        {
            ExportVirtualSystemExSnapshots(scope, vmName, exportDirectory);
        }
    }
}